安全的度過了第一個週末,先訂個小目標:順利完成七天發文吧!!
在剛開始懵懂無知時,連 JavaScript 都還沒摸熟的我因緣巧合之下接觸到了 Vue2,在那時可以說是發現了滿滿黑科技的感覺,遠比第一次碰到 jQuery 還要震撼,立刻就拋棄了新買三天的犀牛書投向了 Vue2 的懷抱然後後面還是還債了,到了三年後被其他前輩洗臉才發現,只會套用好像真的有局限性,因此,這次的主題就這樣誕生啦
讓我們隆重歡迎今天的主角,雙向綁定的最佳功臣,屬性描述器!!
在 ES5 後,Javascript 允許使用者調整屬性的描述器,我們最熟悉的 value 即為其中一個,總共有六個分別是
好了,現在我們對於 defineProPerty 有個基礎的認識了,那我們來稍微做一下當資料更新後的視圖更新吧
首先,我們先宣告一個函數當作 Vue 的實體,在這個時候同時會進行數據的屬性綁定
function Vue(options){
this._data = options.data();
definePropertys(this);
};
接下來,我們要將被接管的 DOM 提供給 Vue,我們會在 Vue 中設定一個屬性來做這件事情
Vue.prototype.$mount = function(el){
this.$el = document.querySelector(el);
this.$el.innerHTML = JSON.stringify(this._data);
return this
};
暫時不考慮樣板,直接將 data 給渲染出來不然後面就沒東西寫了
接下來,我們就可以宣告一個 Vue 實體出來囉,當然,此時的數據是完全沒有設定過的
let vm = new Vue({
data(){
return {
title: '標題',
userInfo: {
username: 'account',
password: 'password'
},
pockets: {
one: 1,
two: 2,
three: 3,
other: {
four: 4
}
},
count: 0
}
}
}).$mount('#app');
接下來就是重頭戲了,將數據進行綁定,此次情況是會將物件深層的內容進行監測,因此除了綁定 data 第一層的屬性以外,我們還需要一個遞迴函式來綁定內部資料
function definePropertys(vue){
let _data = vue._data;
let _dataTemp = {};
function definePropertyDeep(_data){
Object.keys(_data).forEach( key => {
if (_data === vue._data) {
//進行根級資料綁定
}
_dataTemp[key] = _data[key];
//進行深層資料綁定
//若此屬性為物件,繼續遞迴內部屬性
if(_dataTemp[key] instanceof Object) {
definePropertyDeep(_dataTemp[key])
}
})
}
definePropertyDeep(_data);
};
這邊我們已經可以獲得 Vue.data 裡面的所有屬性了,接下來只要將資料進行綁定即可,代碼如下
//根級綁定
Object.defineProperty(vue, key, {
set(v){
_dataTemp[key] = v;
console.log(`setting ${key} with ${v}`);
vue.$el.innerHTML = JSON.stringify(vue._data);
},
get(){
console.log(`getting ${key} with ${_dataTemp[key]}`)
return _dataTemp[key]
},
})
//深層綁定
Object.defineProperty(_data, key, {
set(v){
_dataTemp[key] = v;
console.log(`setting ${key} with ${v}`);
vue.$el.innerHTML = JSON.stringify(vue._data);
},
get(){
console.log(`first getting ${key} with ${_dataTemp[key]}`)
return _dataTemp[key]
},
});
這樣我們的資料就成功地進行綁定囉,在這個情況當有 data 進行更新的時候將會重新渲染整個畫面,那 Vue2 內部的算法將只會渲染相關視圖,這邊就還請各位多摸摸了,我還沒看那麼深啊
今天就到此結束,感謝觀看的各位!